package com.hxkj.shiro;

import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.mgt.DefaultSessionManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;


/**
 * Created by admin on 2017/8/18.
 */
@Configuration
public class ServiceAuthConfig {

    // <!-- Realm实现 -->
    @Bean
    public ServiceRealm serviceRealm() {
        ServiceRealm realm = new ServiceRealm();
        realm.setCachingEnabled(false);
        return realm;
    }

    //<!-- Subject工厂 -->
    @Bean
    public StatelessDefaultSubjectFactory subjectFactory() {
        return new StatelessDefaultSubjectFactory();
    }

    // <!-- 会话管理器 -->
    @Bean
    public DefaultSessionManager sessionManager() {
        DefaultSessionManager sessionManager = new  DefaultSessionManager();
        sessionManager.setSessionValidationSchedulerEnabled(false);
        return sessionManager;
    }

    /**
     * 开启shiro aop注解支持.
     * 使用代理方式;所以需要开启代码支持;
     *
     * @param securityManager
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

    // <!-- 安全管理器 -->
    @Bean
    public DefaultWebSecurityManager securityManager() {
        DefaultWebSecurityManager securityManager =  new DefaultWebSecurityManager();
        //设置realm.
        securityManager.setRealm(serviceRealm());
        // 自定义session管理 使用redis
        securityManager.setSessionManager(sessionManager());
        securityManager.setSubjectFactory(subjectFactory()); //禁用session
        DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
        DefaultSessionStorageEvaluator sessionStorageEvaluator = new DefaultSessionStorageEvaluator();
        sessionStorageEvaluator.setSessionStorageEnabled(false);
        subjectDAO.setSessionStorageEvaluator(sessionStorageEvaluator);
        securityManager.setSubjectDAO(subjectDAO);
        return securityManager;
    }

    @Bean
    public ServiceAuthFilter serviceAuthFilter() {
        return new ServiceAuthFilter();
    }

    @Bean
    public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    /**
     * ShiroFilterFactoryBean 处理拦截资源文件问题。
     * 注意：单独一个ShiroFilterFactoryBean配置是或报错的，因为在
     * 初始化ShiroFilterFactoryBean的时候需要注入：SecurityManager
     *
     Filter Chain定义说明
     1、一个URL可以配置多个Filter，使用逗号分隔
     2、当设置多个过滤器时，全部验证通过，才视为通过
     3、部分过滤器可指定参数，如perms，roles
     *
     */
    @Bean
    public ShiroFilterFactoryBean shirFilter(){
        ShiroFilterFactoryBean shiroFilterFactoryBean  = new ShiroFilterFactoryBean();
        // 必须设置 SecurityManager
        Map<String,Filter> filterMap = new HashMap<>();
        filterMap.put("serviceAuth",new ServiceAuthFilter());
        filterMap.put("logoutAuth",new ServiceLogoutFilter());
        shiroFilterFactoryBean.setFilters(filterMap);
        //拦截器.
        Map<String,String> filterChainDefinitionMap = new LinkedHashMap<>();
        filterChainDefinitionMap.put("/login","anon");
        filterChainDefinitionMap.put("/index","anon");
        filterChainDefinitionMap.put("/validatecode/getcode","anon");
        filterChainDefinitionMap.put("/code/getcode","anon");
        filterChainDefinitionMap.put("/message/sendsms","anon");
        filterChainDefinitionMap.put("/article/saveright","anon");
        filterChainDefinitionMap.put("/file/commonUpload","anon");
//        filterChainDefinitionMap.put("/authrole/getList","anon");
        filterChainDefinitionMap.put("/out","anon");
        filterChainDefinitionMap.put("/static/**","anon");
        filterChainDefinitionMap.put("/combobox/**","anon");
        filterChainDefinitionMap.put("/html/**","anon");
        filterChainDefinitionMap.put("/assets/**","anon");
        filterChainDefinitionMap.put("/css/**","anon");
        filterChainDefinitionMap.put("/js/**","anon");
        filterChainDefinitionMap.put("/statistics/**","anon");
        filterChainDefinitionMap.put("/columnArticle/getlist","anon");
        filterChainDefinitionMap.put("/article/modifyHeat","anon");
        filterChainDefinitionMap.put("/tags/getHotTagsList","anon");
      //  filterChainDefinitionMap.put("/file/imgupload","anon");
        filterChainDefinitionMap.put("/file/ueditorimgupload","anon");

        filterChainDefinitionMap.put("/favicon.ico","anon");
        filterChainDefinitionMap.put("/**", "serviceAuth");
//         TODO: 2017/9/13 暂时不使用拦截
//        filterChainDefinitionMap.put("/**", "anon");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        shiroFilterFactoryBean.setSecurityManager(securityManager());
        return shiroFilterFactoryBean;
    }



}
